package com.zitangkou.user.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.zitangkou.user.domain.IPermissionDomainService;
import com.zitangkou.user.domain.PermissionDomain;
import com.zitangkou.common.enums.CharacterEnum;
import com.zitangkou.common.enums.RespEnum;
import com.zitangkou.common.enums.StatusEnum;
import com.zitangkou.user.enums.permission.PermissionActionEnum;
import com.zitangkou.common.global.GlobalException;
import com.zitangkou.common.global.UserContent;
import com.zitangkou.user.info.PermissionInfo;
import com.zitangkou.user.info.converter.IPermissionInfoConverter;
import com.zitangkou.user.req.permission.AddPermissionReq;
import com.zitangkou.user.req.permission.GetPermissionByPageReq;
import com.zitangkou.user.req.permission.ModifyPermissionReq;
import com.zitangkou.user.resp.permission.PermissionActionResp;
import com.zitangkou.user.service.IPermissionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 权限
 *
 * @author Deng Ningning
 * @version 1.0
 * @date 2020/8/31 16:39
 */

@Slf4j
@Service
public class PermissionServiceImpl implements IPermissionService {

    @Autowired
    private IPermissionDomainService permissionDomainService;

    @Resource
    private IPermissionInfoConverter permissionInfoConverter;

    /**
     * 分页查询权限列表
     *
     * @param req
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.zitangkou.user.model.info.PermissionInfo>
     * @date 2021/2/27 11:24
     */
    @Override
    public IPage<PermissionInfo> getPermissionPage(GetPermissionByPageReq req) {
        IPage<PermissionDomain> page =
                permissionDomainService.selectPageByConditions(req.getCurrent(), req.getSize(), req.getKeyword(), req.getStatus());
        return new Page<PermissionInfo>().setCurrent(page.getCurrent()).setSize(page.getSize())
                .setRecords(permissionInfoConverter.toInfoList(page.getRecords()))
                .setTotal(page.getTotal());
    }

    /**
     * 新增权限
     *
     * @param req
     * @param userContent
     * @return boolean
     * @date 2021/2/27 11:47
     */
    @Override
    public boolean addPermission(AddPermissionReq req, UserContent userContent) {
        String enterpriseId = userContent.getEnterpriseIdNotNull();
        // 验证名称是否重复
        String permissionName = req.getPermissionName();
        checkPermissionNameDuplicate(enterpriseId, permissionName, null);
        // 验证唯一标识符是否重复
        String permissionValue = req.getPermissionValue();
        checkPermissionValueDuplicate(enterpriseId, permissionValue, null);
        // 转化权限操作
        String permissionActions = convertPermissionActions(req.getPermissionActions());
        return permissionDomainService.insertPermission(
                new PermissionDomain().setCreatorId(userContent.getUserId()).setEnterpriseId(enterpriseId)
                        .setPermissionActions(permissionActions)
                        .setPermissionName(permissionName).setPermissionValue(permissionValue).setSortValue(NumberUtils.INTEGER_ONE)
        );
    }

    private String convertPermissionActions(String permissionActions) {
        List<String> permissionActionValueList = Splitter.on(CharacterEnum.COMMA_EN.getValue()).splitToList(permissionActions);
        if (CollectionUtils.isEmpty(permissionActionValueList)) {
            return CharacterEnum.BLANK_STR.getValue();
        }
        return Joiner.on(CharacterEnum.COMMA_EN.getValue())
                .join(permissionActionValueList.stream().map(a -> PermissionActionEnum.valueOf(a.toUpperCase()))
                        .sorted(Comparator.comparingInt(PermissionActionEnum::getSortValue)).map(PermissionActionEnum::getName)
                        .collect(Collectors.toList()));
    }

    /**
     * 修改权限
     *
     * @param req
     * @param userContent
     * @return boolean
     * @date 2021/2/27 11:59
     */
    @Override
    public boolean modifyPermission(ModifyPermissionReq req, UserContent userContent) {
        String userId = userContent.getUserIdNotNull();
        String enterpriseId = userContent.getEnterpriseIdNotNull();
        String permissionId = req.getPermissionId();
        // 验证名称是否重复
        String permissionName = req.getPermissionName();
        if (StringUtils.isNotBlank(permissionName)) {
            checkPermissionNameDuplicate(enterpriseId, permissionName, permissionId);
        }
        // 验证唯一标识符是否重复
        String permissionValue = req.getPermissionValue();
        if (StringUtils.isNotBlank(permissionValue)) {
            checkPermissionValueDuplicate(enterpriseId, permissionValue, permissionId);
        }
        // 转化权限操作
        String permissionActions = null;
        if (StringUtils.isNotBlank(req.getPermissionActions())) {
            permissionActions = convertPermissionActions(req.getPermissionActions());
        }
        return permissionDomainService.updatePermission(
                new PermissionDomain().setPermissionId(permissionId).setPermissionName(permissionName)
                        .setPermissionActions(permissionActions).setModifierId(userId)
                        .setPermissionName(permissionName).setPermissionValue(permissionValue)
                        .setSortValue(req.getSortValue())
        );
    }

    /**
     * 修改权限状态
     *
     * @param permissionId
     * @param status
     * @param userContent
     * @return boolean
     * @date 2021/2/27 12:12
     */
    @Override
    public boolean updatePermissionStatus(String permissionId, StatusEnum status, UserContent userContent) {
        PermissionDomain permissionDomain =
                new PermissionDomain().setPermissionId(permissionId).setStatus(status).setModifierId(userContent.getUserIdNotNull());
        return permissionDomainService.updatePermissionStatus(permissionDomain);
    }

    /**
     * 根据编号查询权限
     *
     * @param permissionId
     * @return com.zitangkou.user.model.domain.PermissionDomain
     * @date 2021/2/27 12:14
     */
    @Override
    public PermissionInfo getPermissionById(String permissionId) {
        return permissionInfoConverter.toInfo(permissionDomainService.getPermissionById(permissionId));
    }

    /**
     * 查询权限所有操作列表
     *
     * @return java.util.List<com.zitangkou.user.model.resp.user.UserLoginActionResp>
     * @author Deng Ningning
     * @date 2020/12/25 11:45
     */
    @Override
    public List<PermissionActionResp> getPermissionActions() {
        return Arrays.asList(PermissionActionEnum.values()).stream()
                .map(a -> new PermissionActionResp().setActionValue(a.getValue()).setActionName(a.getName())
                        .setDefaultCheck(a.getDefaultCheck())).collect(Collectors.toList());
    }

    private void checkPermissionNameDuplicate(String enterpriseId, String permissionName, String permissionId) {
        if (isPermissionNameDuplicate(enterpriseId, permissionName, permissionId)) {
            throw new GlobalException(RespEnum.PERMISSION_NAME_DUPLICATE);
        }
    }

    private void checkPermissionValueDuplicate(String enterpriseId, String permissionValue, String permissionId) {
        if (isPermissionValueDuplicate(enterpriseId, permissionValue, permissionId)) {
            throw new GlobalException(RespEnum.PERMISSION_VALUE_DUPLICATE);
        }
    }

    private boolean isPermissionNameDuplicate(String enterpriseId, String permissionName, String permissionId) {
        PermissionDomain permissionDomain = new PermissionDomain();
        permissionDomain.setEnterpriseId(enterpriseId);
        permissionDomain.setPermissionName(permissionName);
        permissionDomain.setPermissionId(permissionId);
        permissionDomain.setStatus(StatusEnum.ENABLED);
        return permissionDomainService.countByConditions(permissionDomain) > 0;
    }

    private boolean isPermissionValueDuplicate(String enterpriseId, String permissionValue, String permissionId) {
        PermissionDomain permissionDomain = new PermissionDomain();
        permissionDomain.setEnterpriseId(enterpriseId);
        permissionDomain.setPermissionValue(permissionValue);
        permissionDomain.setPermissionId(permissionId);
        permissionDomain.setStatus(StatusEnum.ENABLED);
        return permissionDomainService.countByConditions(permissionDomain) > 0;
    }
}
